package com.hongyi.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hongyi.common.framework.constant.CacheConstants;
import com.hongyi.common.framework.constant.UserConstans;
import com.hongyi.common.framework.exception.ServiceException;
import com.hongyi.common.framework.utils.bean.MapstructUtils;
import com.hongyi.common.framework.utils.string.StringUtils;
import com.hongyi.common.mybatis.page.PageData;
import com.hongyi.common.mybatis.page.PageQuery;
import com.hongyi.common.redis.utils.RedisUtils;
import com.hongyi.system.domain.dto.SysConfigDto;
import com.hongyi.system.domain.vo.SysConfigVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.hongyi.system.domain.SysConfig;
import com.hongyi.system.mapper.SysConfigMapper;
import com.hongyi.system.service.ISysConfigService;

import java.util.*;

@Service
public class SysConfigServiceImpl implements ISysConfigService {

    @Autowired
    private SysConfigMapper sysConfigMapper;

    private LambdaQueryWrapper<SysConfig> buildQueryWrapper(SysConfigDto sysConfigDto) {
        Map<String, Object> params = sysConfigDto.getParams();
        LambdaQueryWrapper<SysConfig> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(sysConfigDto.getConfigName()), SysConfig::getConfigName, sysConfigDto.getConfigName());
        lqw.eq(StringUtils.isNotBlank(sysConfigDto.getConfigType()), SysConfig::getConfigType, sysConfigDto.getConfigType());
        lqw.like(StringUtils.isNotBlank(sysConfigDto.getConfigKey()), SysConfig::getConfigKey, sysConfigDto.getConfigKey());
        lqw.between(params.get("beginTime") != null && params.get("endTime") != null,
                SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
        lqw.orderByAsc(SysConfig::getConfigId);
        return lqw;
    }

    /**
     * 获取参数配置分页列表
     *
     * @param sysConfigDto 参数配置数据
     * @param pageQuery 分页数据
     * @return 参数配置查询结果
     */
    @Override
    public PageData<SysConfigVo> queryConfigPageList(SysConfigDto sysConfigDto, PageQuery pageQuery) {
        LambdaQueryWrapper<SysConfig> lqw = buildQueryWrapper(sysConfigDto);
        IPage<SysConfigVo> result = sysConfigMapper.selectVoPage(pageQuery.build(), lqw);
        return PageData.success(result);
    }

    @Override
    public List<SysConfigVo> selectConfigList(SysConfigDto sysConfigDto) {
        LambdaQueryWrapper<SysConfig> lqw = buildQueryWrapper(sysConfigDto);
        return sysConfigMapper.selectVoList(lqw);
    }

    /**
     * 根据参数编号获取详细信息
     *
     * @param configId 主键
     * @return 参数配置查询结果
     */
    @Override
    public SysConfigVo queryConfigById(Long configId) {
        return sysConfigMapper.selectVoById(configId);
    }

    /**
     * 根据键名查询参数配置信息
     *
     * @param configKey 参数键名
     * @return 参数键值
     */
    @Cacheable(cacheNames = CacheConstants.SYS_CONFIG, key = "#configKey")
    @Override
    public String selectConfigByKey(String configKey) {
        SysConfig retConfig = sysConfigMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
                .eq(SysConfig::getConfigKey, configKey));
        if (ObjectUtil.isNotNull(retConfig)) {
            return retConfig.getConfigValue();
        }
        return StringUtils.EMPTY;
    }

    /**
     * 校验参数键名是否唯一
     *
     * @param sysConfigDto 参数信息
     * @return 结果
     */
    @Override
    public String checkConfigKeyUnique(SysConfigDto sysConfigDto) {
        long configId = ObjectUtil.isNull(sysConfigDto.getConfigId()) ? -1L : sysConfigDto.getConfigId();
        SysConfig config = sysConfigMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
                .eq(SysConfig::getConfigKey, sysConfigDto.getConfigKey()));
        if(ObjectUtil.isNotNull(config) && config.getConfigId() != configId){
            return UserConstans.NOT_UNIQUE;
        }else {
            return UserConstans.UNIQUE;
        }
    }

    /**
     * 新增参数配置
     *
     * @param sysConfigDto 参数配置信息
     * @return 结果
     */
    @CachePut(cacheNames = CacheConstants.SYS_CONFIG, key = "#sysConfigDto.configKey")
    @Override
    public String insertConfig(SysConfigDto sysConfigDto) {
        SysConfig sysConfig = MapstructUtils.convert(sysConfigDto, SysConfig.class);
        int result = sysConfigMapper.insert(sysConfig);
        if (result > 0){
            return Objects.requireNonNull(sysConfig).getConfigValue();
        }
        throw new ServiceException("操作失败");
    }

    /**
     * 修改参数配置
     *
     * @param sysConfigDto 参数配置信息
     * @return 结果
     */
    @CachePut(cacheNames = CacheConstants.SYS_CONFIG, key = "#sysConfigDto.configKey")
    @Override
    public String updateConfig(SysConfigDto sysConfigDto) {
        SysConfig sysConfig = MapstructUtils.convert(sysConfigDto, SysConfig.class);
        SysConfig hisSysConfig = sysConfigMapper.selectById(Objects.requireNonNull(sysConfig).getConfigId());
        if (!StringUtils.equals(hisSysConfig.getConfigKey(), sysConfig.getConfigKey())) {
            RedisUtils.deleteObject(CacheConstants.GLOBAL_REDIS_KEY +CacheConstants.SYS_DICT +":"+ hisSysConfig.getConfigKey());
        }
        int row = sysConfigMapper.updateById(sysConfig);
        if (row>0) {
            return sysConfig.getConfigValue();
        }
        throw new ServiceException("操作失败");
    }

    /**
     * 删除参数配置
     *
     * @param configIds 主键数组
     */
    @Override
    public void deleteConfigByIds(Long[] configIds) {
        for (Long configId : configIds) {
            SysConfig config = sysConfigMapper.selectById(configId);
            if (StringUtils.equals(UserConstans.YES, config.getConfigType())) {
                throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
            }
            RedisUtils.deleteObject(CacheConstants.GLOBAL_REDIS_KEY +CacheConstants.SYS_DICT +":"+ config.getConfigKey());
        }
        sysConfigMapper.deleteBatchIds(Arrays.asList(configIds));
    }

    /**
     * 重置参数缓存数据
     */
    @Override
    public void resetConfigCache() {
        Collection<String> keys = RedisUtils.keys(CacheConstants.GLOBAL_REDIS_KEY + CacheConstants.SYS_CONFIG + ":*");
        RedisUtils.deleteObject(keys);
    }
}
